package com.czh.thread.four;

import java.util.Random;

/**
 * 第四章：共享模型之管程
 * 1.共享问题:多个线程对共享资源进行读写操作时发生指令交错就会存在异常
 * 1)存在得问题：初始化一个值为0,两个线程一个执行+1操作一个执行减一操作，最后的结果不一定为0
 * 2)临界区: 对共享资源进行读写操作
 * 3)竞态条件: 由于代码发生执行顺序不同而导致结果无法预测，则称为竞态条件
 * 2.阻塞状态有: sleep,wait,IO阻塞情况
 * 3.synchronized:
 * 1) 锁对象:synchronized(this)和public synchronized void test()都是锁对象
 * 2) 锁类: synchronized(A.class)
 * 售票窗口实现
 *
 * @author chenzhihua
 * @Date 2024/4/28
 */
public class Test01 {
    public static void main(String[] args) {
        // 随机数生成
        Random random = new Random();
        // 1. 模拟多人买票
//        TicketWindow ticketWindow = new TicketWindow(1000);
//        // 卖出得票数统计
//        List<Integer> amountList = new Vector<>();
//        // 所有线程得集合
//        List<Thread> threadList = new ArrayList<>();

//        // 模拟人购票
//        for (int i = 0; i < 4000; i++) {
//            Thread thread = new Thread(() -> {
//                // 模拟每次售出1~5张票
//                int sell = ticketWindow.sell(random.nextInt(5) + 1);
//                // 模拟不用时间进行购票
//                try {
//                    Thread.sleep(random.nextInt(3000));
//                } catch (InterruptedException e) {
//                    throw new RuntimeException(e);
//                }
//                amountList.add(sell);
//            });
//            threadList.add(thread);
//            thread.start();
//        }
//        // 等待所有线程都执行完在统计
//        for (Thread thread : threadList) {
//            try {
//                thread.join();
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//        }
//        // 统计卖出得票和剩余得票数
//        System.out.println("售出得票数" + amountList.stream().mapToInt(i -> i).sum() + "张");
//        System.out.println("剩余得票数" + ticketWindow.getCount() + "张");

        // 1. 模拟转账
        Account a = new Account(10000);
        Account b = new Account(10000);
        // 模拟转账
        Thread ta = new Thread(() -> {
            for (int i = 0; i < 1000; i++) {
                a.transfer(b, random.nextInt(1000) + 1);
            }
        });

        Thread tb = new Thread(() -> {
            for (int i = 0; i < 1200; i++) {
                b.transfer(a, random.nextInt(1000) + 1);
            }
        });
        ta.start();
        tb.start();
        try {
            ta.join();
            tb.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("总数:" + (a.getMoney() + b.getMoney()) + "元");
    }
}

// 购票窗口
class TicketWindow {
    private int count;

    public TicketWindow(int count) {
        this.count = count;
    }

    // 获取余票数量
    public int getCount() {
        return count;
    }

    // 售票,返回购买得数量
    public synchronized int sell(int amount) {
        if (this.count >= amount) {
            this.count -= amount;
            return amount;
        } else {
            return 0;
        }
    }
}


// 模拟转账
class Account {
    private int money;


    public Account(int money) {
        this.money = money;
    }

    // 获取余额
    public int getMoney() {
        return this.money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    /**
     * 进行转账,存在两个共享变量this.money和target.money
     *
     * @param target 目标账户
     * @param amount 转的金额
     */
    public void transfer(Account target, int amount) {
        synchronized (Account.class) {
            if (this.money >= amount) {
                this.money -= amount;
                target.money += amount;
            }
        }
    }
}